package com.zoe.onelink.business.util;

import com.zoe.onelink.business.cache.bean.IParamEntity;
import com.zoe.onelink.business.constant.CacheConst;
import com.zoe.onelink.business.enumeration.ParamType;
import com.zoe.onelink.business.property.OnelinkBizProperties;
import com.zoe.onelink.business.service.ParamService;
import com.zoe.onelink.common.enumeration.ExceptionCodeEnum;
import com.zoe.onelink.common.exception.ApiException;
import com.zoe.onelink.redis.util.RedisUtil;
import com.zoe.onelink.util.OnelinkContextHolder;
import com.zoe.onelink.util.StrUtil;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import javax.annotation.PostConstruct;
import java.util.Set;

/**
 * <p>标题: </p>
 * <p>描述: </p>
 * <p>版权: Copyright (c) 2021</p>
 * <p>公司: 智业软件股份有限公司</p>
 *
 * @version: 1.0
 * @author: ruansheng
 * @date: 2021-11-23
 */
@RequiredArgsConstructor
@Slf4j
public class ParamCacheUtil {

    private static ParamCacheUtil self;
    private final OnelinkBizProperties.BizParam onelinkBizProperties;
    private final ParamService paramService;

    @PostConstruct
    public void init() {
        self = this;
    }


    /**
     * 获取业务参数值
     * 顺序：个人 -> 科室 -> 院区 -> 全局默认
     *
     * @param paramName 参数名称
     * @return 参数值
     */
    public static String getBizParamValue(@NonNull String paramName) {
        OnelinkBizProperties.BizParamStrategy bizParamStrategy = self.onelinkBizProperties.getStrategy();
        IParamEntity bizParam = bizParamStrategy == OnelinkBizProperties.BizParamStrategy.OPTIMUS
                ? self.paramService.getBizParamValue(paramName)
                : self.paramService.getBizParamValueInDB(paramName);
        // 缓存不存在直接抛出异常
        if (bizParam == null) {
            log.error("[BizParam] [{}] [{}] {}={}", bizParamStrategy.name(), IParamEntity.Type.GLOBAL, paramName, "参数不存在");
            throw ApiException.createEx(ExceptionCodeEnum.BIZ_PARAM_NULL, paramName);
        }
        String paramValue = bizParam.getParamValue();
        if (self.onelinkBizProperties.isLogEnabled()) {
            log.info("[BizParam] [{}] [{}] {}={}", bizParamStrategy.name(), bizParam.getParamType(), paramName, paramValue);
        }
        return paramValue;
    }

    /**
     * 获取指定类型的业务参数值 (暂不提供)
     *
     * @param paramName 参数名称
     * @param paramType 参数类型
     * @return 参数值
     */
    private static String getBizParamValue(@NonNull String paramName, @NonNull ParamType paramType) {
        // 从缓存中获取对应的编码
        String keyCode = OnelinkContextHolder.getString(paramType.getCode());
        if (keyCode == null) {
            throw ApiException.createEx(ExceptionCodeEnum.BIZ_PARAM_NULL, paramName);
        }
        IParamEntity bizParam;
        switch (paramType) {
            case USER:
                bizParam = self.paramService.getUserParam(paramName, keyCode, true);
                break;
            case DEPT:
                bizParam = self.paramService.getDeptParam(paramName, keyCode, true);
                break;
            case DISTRICT:
                bizParam = self.paramService.getDistrictParam(paramName, keyCode, true);
                break;
            case GLOBAL:
                bizParam = self.paramService.getGlobalParam(paramName, true);
                break;
            default:
                bizParam = null;
                break;
        }
        if (bizParam == null) {
            throw ApiException.createEx(ExceptionCodeEnum.BIZ_PARAM_NULL, paramName);
        }
        return bizParam.getParamValue();
    }


    /**
     * 移除参数缓存
     *
     * @param paramName 参数名称
     * @return 被移除的参数缓存数量
     */
    public static Long delParamCache(String paramName) {
        if (StrUtil.isBlank(paramName)) {
            throw ApiException.createEx(ExceptionCodeEnum.KEY_NOT_NULL, "PARAM_CACHE_KEY");
        }
        Set<String> delKeys = RedisUtil.keys(CacheConst.PARAMS_BIZ_NAME_MATCH_PRE + paramName + "*");
        return delCaches(delKeys);
    }

    /**
     * 清空所有参数缓存
     *
     * @return 被移除的参数缓存数量
     */
    public static Long clearParamCaches() {
        log.info("[BizParam] 开始清理缓存");
        Set<String> delKeys = RedisUtil.keys(CacheConst.PARAMS_ALL_MATCH_PRE);
        self.paramService.clearLocalCache();
        return delCaches(delKeys);
    }

    /**
     * 移除缓存
     *
     * @param delKeys 缓存Key
     * @return 被移除的参数缓存数量
     */
    private static Long delCaches(Set<String> delKeys) {
        if (delKeys == null || delKeys.isEmpty()) {
            return 0L;
        }
        return RedisUtil.deleteKeys(delKeys);
    }

}
